package com.yf.redis;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 分布式Redis锁
 */
@Slf4j
@Component
public class DistributedRedisLock {

    @Resource
    private RedissonClient redissonClient;

    // 加锁
    public Boolean lock(String lockName) {
        return lock(lockName,15);
    }
    /**
     * 
     * @param: [java.lang.String, long]
     * @param:lockHoldTime 锁的持有时间，超过该时间则自动释放锁
     * @date: 2024/3/26 14:01
     * @return: java.lang.Boolean       
     * @author: yangfeng
     **/
    public Boolean lock(String lockName,long lockHoldTime) {
        if (redissonClient == null) {
            log.info("DistributedRedisLock redissonClient is null");
            return false;
        }

        try {
            RLock lock = redissonClient.getLock(lockName);
            // 锁15秒后自动释放，防止死锁
            lock.lock(lockHoldTime, TimeUnit.SECONDS);

            log.info("Thread [{}] DistributedRedisLock lock [{}] success", Thread.currentThread().getName(), lockName);
            // 加锁成功
            return true;
        } catch (Exception e) {
            log.error("DistributedRedisLock lock [{}] Exception:", lockName, e);
            return false;
        }
    }
    /**
     * 
     * @param: [java.lang.String, long, long, java.util.concurrent.TimeUnit]
     * @param:lockName 需要锁定的业务的值，一般格式为前缀+业务标识id
     * @param:waitTime 当前线程请求进来发现其他线程持有该锁，等待的时间，超时则获取锁失败，返回false
     * @param:releaseTime 线程持有锁的时间，超过该时间则自动释放
     * @param:timeUnit 锁的等待时间和持有时间对应的时间单位
     * @date: 2024/3/26 9:54
     * @return: java.lang.Boolean       
     * @author: yangfeng
     **/
    public Boolean lock(String lockName,long waitTime,long releaseTime,TimeUnit timeUnit){
        log.info("【锁的】当前线程 threadName = {}",Thread.currentThread().getName());
        if (redissonClient == null) {
            log.info("DistributedRedisLock redissonClient is null");
            return false;
        }
        RLock lock = redissonClient.getLock(lockName);
        try {
            if(lock.tryLock(waitTime,releaseTime,timeUnit)){
                log.info("Thread [{}] DistributedRedisLock lock [{}] success", Thread.currentThread().getName(), lockName);
                return true;
            }else{
                log.info("Thread [{}] DistributedRedisLock lock [{}] fail", Thread.currentThread().getName(), lockName);
                return false;
            }

        } catch (Exception e) {
//            throw new RuntimeException(e);
            log.error("DistributedRedisLock unlock [{}] Exception:", lockName, e);
            return false;
        }

    }

    // 释放锁
    public Boolean unlock(String lockName) {
        if (redissonClient == null) {
            log.info("DistributedRedisLock redissonClient is null");
            return false;
        }

        try {
            RLock lock = redissonClient.getLock(lockName);
            if(lock.isLocked() && lock.isHeldByCurrentThread()){
                log.info("【解锁的】当前线程 threadName = {}",Thread.currentThread().getName());
                lock.unlock();
                log.info("Thread [{}] DistributedRedisLock unlock [{}] success", Thread.currentThread().getName(), lockName);
                return true;
            }
            return false;
            // 释放锁成功
        } catch (Exception e) {
            log.error("DistributedRedisLock unlock [{}] Exception:", lockName, e);
            return false;
        }
    }
}
